package com.liyi.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import javax.inject.Inject;

import com.liyi.dao.EmpSalaryDao;
import com.liyi.dao.FormulaDao;
import com.liyi.dao.SalaryItemDao;
import com.zero.basic.exception.SmsDaoException;
import com.zero.basic.exception.SmsErrorConstant;
import com.zero.basic.exception.SmsRuntimeException;
import com.zero.basic.exception.SmsStatusCode;
import com.zero.basic.util.SimpleDateUtil;
import com.zero.mms.model.EmpSalary;

@Service("empSalaryService")
@Transactional(rollbackFor = Exception.class)
public class EmpSalaryService {
	
	@Inject
	private EmpSalaryDao empSalaryDaoLiyi;
	@Inject
	private FormulaDao formulaDao;
	@Inject
	private SalaryItemDao salaryItemDaoLiyi;
	
	/* 默认当前年下，获取某 [员工] 在某 [月] 的所有 [工资项] 的键值数据 */
	public List<EmpSalary> getESsByEmpIdAndMonth(Integer empId, Integer month) throws SmsRuntimeException {
		try {
			// 将月份数字处理成日期格式“yyyy-MM”，默认当前年
			String date;
			if (month.compareTo(9) > 0) {
				date = SimpleDateUtil.getCurrentYear() + "-" + month.toString();
			} else {
				date = SimpleDateUtil.getCurrentYear() + "-0" + month.toString();
			}
			
			List<EmpSalary> empSalaries = empSalaryDaoLiyi.getESsByEmpIdAndDate(empId, date, "已发");
			return empSalaries;
		} catch (Exception e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
	
	/* 计算某 [员工] 在某 [月] 的所有 [计算工资项] 的值并写入数据库 */
	@Transactional(isolation = Isolation.SERIALIZABLE)
	public void calculate(Integer empId, Integer month) throws SmsRuntimeException {
		try {
			// 将月份数字处理成日期格式“yyyy-MM”，默认当前年
			String date;
			if (month.compareTo(9) > 0) {
				date = SimpleDateUtil.getCurrentYear() + "-" + month.toString();
			} else {
				date = SimpleDateUtil.getCurrentYear() + "-0" + month.toString();
			}
			
			// 获取该员工id在该月的所有工资项
			List<EmpSalary> empSalaries = empSalaryDaoLiyi.getESsByEmpIdAndDate(empId, date, "已发");
			
			// 筛选该员工的计算工资项目并计算工资值
			for (EmpSalary empSalary : empSalaries) {
				System.out.println("---- 正在处理的 emp_salary记录 id：" + empSalary.getEmpSalaryId() + " ----");
				// 验证该 emp_salary记录 绑定的工资项是否为 计算项目
				if (isCalItem(empSalary.getSalaryItemId())) {
					// 获取该计算项目对应公式的左端运算子
					Integer left = formulaDao.getLeftOperand(empId, date, Integer.parseInt(empSalary.getSalaryItemId()));
					// 获取右端运算子
					Double right = formulaDao.getRightOperand(empId, date, Integer.parseInt(empSalary.getSalaryItemId()));
					// 获取操作符
					String operator = formulaDao.getOperator(empId, date, Integer.parseInt(empSalary.getSalaryItemId()));
					// 根据操作符匹配运算操作，将结果写入该工资项的工资值栏位
					if ("*".equals(operator)) {
						// 计算工资值
						Double result = left * right;
						// 声明SQL语句
						empSalaryDaoLiyi.updateNumById(result.intValue(), empSalary.getEmpSalaryId());
					}
				}
			}
			
			Integer finalEsId = null;
			for (EmpSalary empSalary : empSalaries) {
				if (isFinalItem(empSalary.getSalaryItemId())) {
					finalEsId = empSalary.getEmpSalaryId();
					break;
				}
			}
			Double finalSalary = 0.0;
			for (EmpSalary empSalary : empSalaries) {
				if (isAddItem(empSalary.getSalaryItemId())) {
					finalSalary += Double.parseDouble(empSalary.getEmpSalaryNum());
				}
				else if (isMinusItem(empSalary.getSalaryItemId())) {
					finalSalary -= Double.parseDouble(empSalary.getEmpSalaryNum());
				}
			}
			empSalaryDaoLiyi.updateNumById(finalSalary.intValue(), finalEsId);
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
	
	/* 验证某 [工资项] 是否为“计算项目”*/
	private boolean isCalItem(String salaryItemId) throws SmsRuntimeException {
		try {
			String type;
			type = salaryItemDaoLiyi.getSalaryItemTypeBySalaryItemId(salaryItemId);
			if ("计算".equals(type)) {
				System.out.println("---- 发现一个【计算】项目，salary_item_id : " + salaryItemId + "----");
				return true;
			}
			// 否则不是“计算项目”
			return false;
		} catch (SmsDaoException e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
	
	/* 验证某 [工资项] 是否为“实发项目”*/
	private boolean isFinalItem(String salaryItemId) throws SmsRuntimeException {
		try {
			String type;
			type = salaryItemDaoLiyi.getSalaryItemTypeBySalaryItemId(salaryItemId);
			if ("实发".equals(type)) {
				System.out.println("---- 发现一个【实发】项目，salary_item_id : " + salaryItemId + "----");
				return true;
			}
			// 否则不是“实发项目”
			return false;
		} catch (SmsDaoException e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
	
	/* 验证某 [工资项] 的 增减类型 */
	private boolean isAddItem(String salaryItemId) throws SmsRuntimeException {
		try {
			String add;
			add = salaryItemDaoLiyi.getSalaryItemAddTypeBySalaryItemId(salaryItemId);
			if ("增加".equals(add)) {
				System.out.println("---- 发现一个【增加】项目，salary_item_id : " + salaryItemId + "----");
				return true;
			}
			// 否则不是“增加项目”
			return false;
		} catch (SmsDaoException e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
	
	/* 验证某 [工资项] 的 增减类型 */
	private boolean isMinusItem(String salaryItemId) throws SmsRuntimeException {
		try {
			String add;
			add = salaryItemDaoLiyi.getSalaryItemAddTypeBySalaryItemId(salaryItemId);
			if ("减少".equals(add)) {
				System.out.println("---- 发现一个【减少】项目，salary_item_id : " + salaryItemId + "----");
				return true;
			}
			// 否则不是“减少项目”
			return false;
		} catch (SmsDaoException e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
	
	/* 设置某 [员工] 的 在某 [月] 的 [工资项] 状态为 发放 */
	public void distribute(Integer empId, Integer month) throws SmsRuntimeException {
		try {
			// 将月份数字处理成日期格式“yyyy-MM”，默认当前年
			String date;
			if (month.compareTo(9) > 0) {
				date = SimpleDateUtil.getCurrentYear() + "-" + month.toString();
			} else {
				date = SimpleDateUtil.getCurrentYear() + "-0" + month.toString();
			}
			List<EmpSalary> empSalaries = empSalaryDaoLiyi.getESsByEmpIdAndDate(empId, date, "已发");
			for (EmpSalary empSalary : empSalaries) {
				empSalaryDaoLiyi.updateStateById("已发", empSalary.getEmpSalaryId());
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
	
	/* 根据 [员工工资项]id 获取 [工资项]名称 */
	public String getSalaryItemNameByEmpSalaryId(Integer esId) throws SmsRuntimeException {
		try {
			return empSalaryDaoLiyi.getSalaryItemNameByEmpSalaryId(esId);
		} catch (Exception e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
	
	/* 根据 [员工工资项]id 获取 [工资项]显示顺序 */
	public Integer getSalaryItemOrderByEmpSalaryId(Integer esId) throws SmsRuntimeException {
		try {
			return empSalaryDaoLiyi.getSalaryItemOrderByEmpSalaryId(esId);
		} catch (Exception e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}

	/* 获取 [员工工资项] 的改动 [工资值] 并写入数据库 */
	public void save(Integer empSalaryId, Integer empSalaryNum) throws SmsRuntimeException {
		try {
			empSalaryDaoLiyi.updateNumById(empSalaryNum, empSalaryId);
		} catch (Exception e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
	
	/* 生成计算项目关联信息 */
	@Transactional(isolation = Isolation.SERIALIZABLE)
	public void insertEmpSalaryItem(Integer empId, Integer month) throws SmsRuntimeException {
		try {
			// 将月份数字处理成日期格式“yyyy-MM”，默认当前年
			String date;
			if (month.compareTo(9) > 0) {
				date = SimpleDateUtil.getCurrentYear() + "-" + month.toString();
			} else {
				date = SimpleDateUtil.getCurrentYear() + "-0" + month.toString();
			}
			
			List<Integer> salaryItemIds = salaryItemDaoLiyi.getSalaryItemIds();
			List<EmpSalary> currents = empSalaryDaoLiyi.getESsByEmpIdAndDate(empId, date, null);
			
			for (Integer salaryItemId : salaryItemIds) {
				boolean noExistItem = true;
				for (EmpSalary empSalary : currents) {
					if (Integer.parseInt(empSalary.getSalaryItemId()) == salaryItemId) {
						noExistItem = false;
						break;
					}
				}
				if (noExistItem) {
					EmpSalary es = new EmpSalary();
					es.setEmpId(empId);
					es.setEmpSalaryDate(date);
					es.setSalaryItemId(salaryItemId+"");
					empSalaryDaoLiyi.add(es);
				}
				
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			throw new SmsRuntimeException(SmsStatusCode.SERVER_ERROR, SmsErrorConstant.WEB_APPLICATION, "服务器异常");
		}
	}
}
